package com.bieber.smartpost.invoke;

import com.bieber.smartpost.util.Utils;
import com.jbeer.framework.annotation.Bean;

import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * Created by bieber on 2014/11/6.
 */
@Bean
public class BatchHttpInvokeResultQueue{

    private static volatile ConcurrentHashMap<String,SafeHttpResult> BATCH_QUEUE = new ConcurrentHashMap<String, SafeHttpResult>();

    public static void putResult(String invokeId,HttpInvokerResult result){
         Utils.COMMONS_LOGGER.debug("request "+invokeId+" new result "+result.toString());
         SafeHttpResult results = BATCH_QUEUE.get(invokeId);
         if(results==null){
             results=new SafeHttpResult();
             SafeHttpResult oldValue =BATCH_QUEUE.putIfAbsent(invokeId,results);
             if(oldValue!=null){
                 results=oldValue;
             }
         }
        results.offer(result);
        Utils.COMMONS_LOGGER.debug("current queue size "+results.size());
    }


    public static HttpInvokerResult getResult(String invokeId){
        SafeHttpResult results = BATCH_QUEUE.get(invokeId);
        if(results==null||results.size()<=0){
            return null;
        }
        return results.pop();
    }

    static class SafeHttpResult extends ReentrantReadWriteLock{

        private LinkedList<HttpInvokerResult> results = new LinkedList<HttpInvokerResult>();

        private volatile  int size;
        public void offer(HttpInvokerResult result){
            Lock lock = writeLock();
            try {
                lock.lockInterruptibly();
            } catch (InterruptedException e) {
                Utils.COMMONS_LOGGER.debug("lock exception",e);
            }
            try{
                results.addFirst(result);
                size++;
            }finally {
                lock.unlock();
            }
        }

        public int size(){
            return size;
        }

        public HttpInvokerResult pop(){
            Lock lock  = readLock();
            try {
                lock.lockInterruptibly();
            } catch (InterruptedException e) {
                Utils.COMMONS_LOGGER.debug("lock exception", e);
            }
            try{
                size--;
                return results.pop();
            }finally {
                lock.unlock();
            }
        }
    }
}
